{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "ML with BLockchain.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "cells": [
    {
      "metadata": {
        "id": "ayecVtNpGdtB",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "# Trail Experiment to do  Machine Learning on Blockchain(BlockFL)\n"
      ]
    },
    {
      "metadata": {
        "id": "X6o8nr8NGdtE",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "#### Imports"
      ]
    },
    {
      "metadata": {
        "id": "f2p5UZWTGdtG",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "import pandas as pd\n",
        "import numpy as np\n",
        "import json\n",
        "from sklearn import preprocessing\n",
        "from sklearn.metrics import confusion_matrix\n",
        "from sklearn.linear_model import LogisticRegression\n",
        "from sklearn.model_selection import train_test_split\n",
        "from flask import Flask, Response, request, jsonify\n",
        "from web3 import Web3"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "Sl3bveQnGdtN",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "# How to share configuration\n",
        "\n",
        "Decide on the configuration that should be used by owner ,user, as well as splitting the data to be used by each."
      ]
    },
    {
      "metadata": {
        "id": "lJhLWF25GdtO",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "#### Data"
      ]
    },
    {
      "metadata": {
        "id": "e36lQJ3AGdtQ",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        },
        "outputId": "a5d7a2e0-912d-47e8-d8c6-6a3cc2cef176"
      },
      "cell_type": "code",
      "source": [
        "input = pd.read_csv('Iris.csv')\n",
        "input.head()"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>Id</th>\n",
              "      <th>SepalLengthCm</th>\n",
              "      <th>SepalWidthCm</th>\n",
              "      <th>PetalLengthCm</th>\n",
              "      <th>PetalWidthCm</th>\n",
              "      <th>Species</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>5.1</td>\n",
              "      <td>3.5</td>\n",
              "      <td>1.4</td>\n",
              "      <td>0.2</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>4.9</td>\n",
              "      <td>3.0</td>\n",
              "      <td>1.4</td>\n",
              "      <td>0.2</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>4.7</td>\n",
              "      <td>3.2</td>\n",
              "      <td>1.3</td>\n",
              "      <td>0.2</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>4.6</td>\n",
              "      <td>3.1</td>\n",
              "      <td>1.5</td>\n",
              "      <td>0.2</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>5.0</td>\n",
              "      <td>3.6</td>\n",
              "      <td>1.4</td>\n",
              "      <td>0.2</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   Id  SepalLengthCm  SepalWidthCm  PetalLengthCm  PetalWidthCm      Species\n",
              "0   1            5.1           3.5            1.4           0.2  Iris-setosa\n",
              "1   2            4.9           3.0            1.4           0.2  Iris-setosa\n",
              "2   3            4.7           3.2            1.3           0.2  Iris-setosa\n",
              "3   4            4.6           3.1            1.5           0.2  Iris-setosa\n",
              "4   5            5.0           3.6            1.4           0.2  Iris-setosa"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 2
        }
      ]
    },
    {
      "metadata": {
        "id": "038qNfjVGdtW",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "# Splitting between training and testing\n",
        "X_train, X_test, y_train, y_test = train_test_split(input.loc[:,input.columns != 'Species'], input['Species'], test_size=0.2)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "FWhWO_ftGdtZ",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "#### Setting up configurations to access smart contract"
      ]
    },
    {
      "metadata": {
        "id": "7G0Ouvj7Gdta",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "w3 = Web3(Web3.HTTPProvider(\"http://127.0.0.1:8545\"))\n",
        "        \n",
        "contract_abi = '[{\"constant\": false,\"inputs\": [{\"name\": \"_encoded_parameters\",\"type\": \"string\"}],\"name\": \"setModelParameters\",\"outputs\": [],\"payable\": false,\"stateMutability\": \"nonpayable\",\"type\": \"function\"},{\"inputs\": [],\"payable\": false,\"stateMutability\": \"nonpayable\",\"type\": \"constructor\"},{\"constant\": true,\"inputs\": [],\"name\": \"getModelParameters\",\"outputs\": [{\"name\": \"_encoded_parameters\",\"type\": \"string\"}],\"payable\": false,\"stateMutability\": \"view\",\"type\": \"function\"}]'\n",
        "contract_address = Web3.toChecksumAddress('0x748b9e15ac55f06bdd4b605fa6d1be5d1e7c2ed7')\n",
        "\n",
        "ml_contract = w3.eth.contract(address=contract_address, abi=contract_abi)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "bnBVRK8VGdtd",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "# Section 1: Miner\n",
        "\n",
        "This is the part that will be used by the miner. Here, the model is trained on private data, and the model parameters are uploaded to the smart contract. We should ensure that the address of the user uploading this data is the same as the owner of the smart contract."
      ]
    },
    {
      "metadata": {
        "id": "7-NfNjdTGdte",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Training"
      ]
    },
    {
      "metadata": {
        "id": "-WXJdeP2Gdtf",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 156
        },
        "outputId": "0c3c5b07-94c0-486d-9f23-5f2da76a1d21"
      },
      "cell_type": "code",
      "source": [
        "cls = LogisticRegression()\n",
        "f = cls.fit(X_train,y_train)\n",
        "cls.coef_"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/sklearn/linear_model/logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
            "  FutureWarning)\n",
            "/usr/local/lib/python3.6/dist-packages/sklearn/linear_model/logistic.py:460: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.\n",
            "  \"this warning.\", FutureWarning)\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[-0.08334802,  0.82685778,  1.32982985, -1.54404986, -0.68929451],\n",
              "       [-0.03085569,  0.27787651, -1.56724838,  1.16275345, -0.9343508 ],\n",
              "       [ 0.0805138 , -1.96088465, -1.60096012,  1.56651241,  1.46921822]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 6
        }
      ]
    },
    {
      "metadata": {
        "id": "mbp0k_jpGdti",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Encode model parameters to json"
      ]
    },
    {
      "metadata": {
        "id": "ijqMJC4hGdtl",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 54
        },
        "outputId": "fdfb0524-4a6b-4a00-bc4d-86aefc7584ca"
      },
      "cell_type": "code",
      "source": [
        "encoded = json.dumps((cls.coef_.tolist(), cls.intercept_.tolist(), cls.classes_.tolist()))\n",
        "encoded"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'[[[-0.08334802264347155, 0.8268577762491404, 1.3298298509731281, -1.5440498568908056, -0.6892945149592731], [-0.030855686001170394, 0.27787651391754953, -1.5672483835342919, 1.1627534525911178, -0.9343508024181482], [0.08051380217588691, -1.9608846474809358, -1.6009601152891235, 1.5665124101981365, 1.4692182230421642]], [0.37330079088218426, 1.3203209080330014, -1.316606447551601], [\"Iris-setosa\", \"Iris-versicolor\", \"Iris-virginica\"]]'"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "metadata": {
        "id": "RfkDrl-DGdtp",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Upload to Smart Contract"
      ]
    },
    {
      "metadata": {
        "id": "jS-bYe4PGdtr",
        "colab_type": "code",
        "colab": {},
        "outputId": "a744e1f7-f78e-425d-bbf0-0dee81a9d633"
      },
      "cell_type": "code",
      "source": [
        "w3.eth.defaultAccount = w3.eth.accounts[0]\n",
        "    \n",
        "tx_hash = ml_contract.functions.setModelParameters(\n",
        "    encoded\n",
        ")\n",
        "tx_hash = tx_hash.transact()\n",
        "\n",
        "# Wait for transaction to be mined...\n",
        "w3.eth.waitForTransactionReceipt(tx_hash)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "AttributeDict({'transactionHash': HexBytes('0xaad2afbe441f5c83998668b1b84f3f05f1b7e96de35def1ad2e91e15c16785f2'),\n",
              " 'transactionIndex': 0,\n",
              " 'blockHash': HexBytes('0x1bdc023923767ea5e2497c02db655c3f842591c46038d8211ac00caf9ec13364'),\n",
              " 'blockNumber': 5,\n",
              " 'from': '0x6256b974e3200fdb2d299beb29f566777cb25b7b',\n",
              " 'to': '0x748b9e15ac55f06bdd4b605fa6d1be5d1e7c2ed7',\n",
              " 'gasUsed': 294304,\n",
              " 'cumulativeGasUsed': 294304,\n",
              " 'contractAddress': None,\n",
              " 'logs': [],\n",
              " 'status': 1,\n",
              " 'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'),\n",
              " 'v': '0x1b',\n",
              " 'r': '0x6a815ed33348dd82e6bb937932e5e61acd01842b4fa12fc032e85e77adbcae19',\n",
              " 's': '0x5ec872ac37914e878ab6d7d63832ed4146d229d7387a4e30b0aa4b578527713a'})"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 21
        }
      ]
    },
    {
      "metadata": {
        "id": "f5wl-Vf7Gdtw",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "# Module 2: User\n",
        "\n",
        "Now we will check how the user can retrieve the model parameters from the smart contract, and create a logistic regression model based on them. "
      ]
    },
    {
      "metadata": {
        "id": "Un4lg51UGdtx",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Retrieving data from smart contract and decoding"
      ]
    },
    {
      "metadata": {
        "id": "EIfb3Lt0Gdty",
        "colab_type": "code",
        "colab": {},
        "outputId": "8f9ed87c-ac14-49cf-d508-e875bdcaf401"
      },
      "cell_type": "code",
      "source": [
        "w3.eth.defaultAccount = w3.eth.accounts[1]\n",
        "\n",
        "encoded_parameters = ml_contract.functions.getModelParameters().call()\n",
        "decoded_parameters = json.loads(encoded_parameters)\n",
        "decoded_parameters"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[[[0.40043028547787896,\n",
              "   1.377941589045666,\n",
              "   -2.1574975875300777,\n",
              "   -0.9585691538326847],\n",
              "  [0.49646783655567767,\n",
              "   -1.6529904209609068,\n",
              "   0.559813705284916,\n",
              "   -1.4815214212935361],\n",
              "  [-1.5855703912796488,\n",
              "   -1.3108635533360338,\n",
              "   2.2082364626024265,\n",
              "   2.4434104076295045]],\n",
              " [0.23609827350167537, 0.8695054088949591, -1.0751280708940156],\n",
              " ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 22
        }
      ]
    },
    {
      "metadata": {
        "id": "4GtkGnXuGdt2",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Creating model based on parameters retrieved"
      ]
    },
    {
      "metadata": {
        "id": "982gFly1Gdt3",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "cls = LogisticRegression()\n",
        "cls.coef_ = np.array(decoded_parameters[0])\n",
        "cls.intercept_ = np.array(decoded_parameters[1])\n",
        "cls.classes_ = np.array(decoded_parameters[2])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "mgr1RPhLGdt6",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Performing Prediction"
      ]
    },
    {
      "metadata": {
        "id": "i8nMD350Gdt7",
        "colab_type": "code",
        "colab": {},
        "outputId": "f04adb32-389d-4114-a95b-7d9061bee9b9"
      },
      "cell_type": "code",
      "source": [
        "predictions = cls.predict(X_test);\n",
        "result = pd.DataFrame(np.vstack((predictions, y_test)).T,columns=['Predicted Outcomes','Actual Outcomes'])\n",
        "result.head()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>Predicted Outcomes</th>\n",
              "      <th>Actual Outcomes</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>Iris-setosa</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>Iris-virginica</td>\n",
              "      <td>Iris-virginica</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>Iris-setosa</td>\n",
              "      <td>Iris-setosa</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>Iris-versicolor</td>\n",
              "      <td>Iris-versicolor</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>Iris-virginica</td>\n",
              "      <td>Iris-virginica</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "  Predicted Outcomes  Actual Outcomes\n",
              "0        Iris-setosa      Iris-setosa\n",
              "1     Iris-virginica   Iris-virginica\n",
              "2        Iris-setosa      Iris-setosa\n",
              "3    Iris-versicolor  Iris-versicolor\n",
              "4     Iris-virginica   Iris-virginica"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 24
        }
      ]
    },
    {
      "metadata": {
        "id": "ZkEZ1fHZGdt_",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "### Showing resulting metrics"
      ]
    },
    {
      "metadata": {
        "id": "Dt76RgrqGduA",
        "colab_type": "code",
        "colab": {},
        "outputId": "93261a41-54aa-4aae-a267-44156d2c0405"
      },
      "cell_type": "code",
      "source": [
        "accuracy = np.sum(predictions == y_test) / y_test.shape[0] * 100\n",
        "conf_matrix = confusion_matrix(predictions, y_test)\n",
        "precision = conf_matrix[0,0] / (conf_matrix[0,0] + conf_matrix[0,1]) * 100\n",
        "\n",
        "print(conf_matrix)\n",
        "print(\"Accuracy: {0:.2f}%\".format(accuracy))\n",
        "print(\"Precision: {0:.2f}%\".format(precision))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[[11  0  0]\n",
            " [ 0 10  1]\n",
            " [ 0  2  6]]\n",
            "Accuracy: 90.00%\n",
            "Precision: 100.00%\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "metadata": {
        "id": "8_Al2AiYGduF",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}